[[!meta title="Bash Completion"]]
[[!meta date="Tue 2016-08-30 05:01:47 AM"]]

Links
---

[Intro to bash completion](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1)

Basics
---

Most Debian installed bash completions live under `/usr/share/bash_completion/completions`

```{.bash .numberLines}
# the first argument ($1) is the name of the command whose  arguments are being completed
# the second argument ($2) is the word being completed,
# and the third argument ($3) is the word preceding the word  being  completed  on the current command line
# In the context of this function the following variables are defined:
# COMP_LINE, COMP_POINT, COMP_KEY, and COMP_TYPE
# as well as COMP_WORDS and COMP_CWORD
#  It must put the possible completions in the COMPREPLY array
# See bash(1) '^  Programmable Completion' for more information
_some_function() {
  local cur cmd
  cur=${COMP_WORDS[$COMP_CWORD]}
  cmd=( "${COMP_WORDS[@]}" )
}
complete -F _some_function command
```

`complete` options
---

Some complete options you want:

* `-o bashdefault` - if no completions are found do the bash default thing
* `-o default` - readline completions if both the complete function and bash expansions fail
* `-o nospace` - don't append a space at the end of matches (useful if you're doing directory stuffs)
* `-S or -P` - a prefix or suffix that is added at the end of a completion generated by the function passed to `complete -F`

Example
---

```{.bash .numberLines}
# Many of the ideas presented in this script were stolen
# in-part or wholesale from
# <https://github.com/git/git/blob/master/contrib/completion/git-completion.bash>
__scap_subcommands=
__scap_get_subcommands() {
    if [ -n "$__scap_subcommands" ]; then
        return
    fi

    __scap_subcommands=$(scap --_autocomplete)
}

_scap() {
    local cur cmd=() sub rep

    cur=${COMP_WORDS[$COMP_CWORD]}
    cmd=( "${COMP_WORDS[@]}" )

    if (( COMP_CWORD == 1 )); then
        __scap_get_subcommands
        rep=$( compgen -W "$__scap_subcommands" -- "$cur" )
        COMPREPLY=( $rep )
        return
    fi

    # limit the command to autocomplete to the first 3 words
    if (( COMP_CWORD >= 2 )); then
        # don't complete any sub-subcommands, only options
        if \[[ -n "$cur" && "${cur:0:1}" != '-' ]]; then
            COMPREPLY=()
            return
        fi
        cmd=( "${COMP_WORDS[@]:0:3}" )
    fi

    # replace the last word in the command with '--_autocomplete'
    cmd[ $(( ${#cmd[@]} - 1 )) ]='--_autocomplete'

    rep=$( compgen -W "$( ${cmd[@]} )" -- "$cur" )

    COMPREPLY=( $rep )
}

# By default append nospace except when completion comes from _scap
complete -S' ' -o bashdefault -o default -o nospace -F _scap scap
```
